package com.hongji.lms5xxcommunicator.opc.bootstrap;

import com.hongji.lms5xxcommunicator.entity.ScanPointEntity;
import com.hongji.lms5xxcommunicator.realtime.PointDtoMapper;
import com.hongji.lms5xxcommunicator.realtime.WsTransferService;
import com.hongji.lms5xxcommunicator.grid.RasterGrid;
import com.hongji.lms5xxcommunicator.grid.config.RasterGridHolder;
import com.hongji.lms5xxcommunicator.grid.export.GridDeltaPayload;
import com.hongji.lms5xxcommunicator.grid.util.Rasterizer;
import com.hongji.lms5xxcommunicator.mapper.ScanPointDataMapper;
import com.hongji.lms5xxcommunicator.storage.EpochManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.List;

@Slf4j
@RequiredArgsConstructor
public class GridBootstrapper {

    private final int pageSize;
    private final int throttleMs;

    private final ScanPointDataMapper scanPointDataMapper;
    private final RasterGridHolder rasterGridHolder;
    private final WsTransferService wsTransfer;
    private final PointDtoMapper pointDtoMapper; // keep
    private final EpochManager epochManager;     // ⭐ 建议注入

    public void bootstrapStreamFromDb() {
        final long epoch = epochManager.getCurrent(); // ⭐ 只读当前会话
        long lastId = 0L; boolean first = true;

        RasterGrid grid = rasterGridHolder.get();

        // —— 可选：稳健色尺（2%~98% 百分位）并冻结，避免负值拉黑 —— //
        final int RES = 20000;
        java.util.Random rnd = new java.util.Random(202503);
        java.util.ArrayList<Double> zReservoir = new java.util.ArrayList<>(RES);

        while (true) {
            // ⭐ 带 epoch 的分页（若你已加 ByEpoch 接口就用它）
            List<ScanPointEntity> rawPage =
                    scanPointDataMapper.selectPageAfterIdByEpoch(epoch, lastId, pageSize);
            if (rawPage == null || rawPage.isEmpty()) break;

            // 采样 z 用于色尺
            for (ScanPointEntity e : rawPage) {
                if (e != null && e.getZ() != null) {
                    if (zReservoir.size() < RES) zReservoir.add(e.getZ());
                    else {
                        int j = rnd.nextInt(Integer.MAX_VALUE) % Math.max(1, (int)(lastId + zReservoir.size()));
                        if (j < RES) zReservoir.set(j, e.getZ());
                    }
                }
            }

            // ⭐ 只做一次栅格化：原始点 -> mergeWithDelta
            GridDeltaPayload payload = grid.mergeWithDelta(rawPage, null);
            wsTransfer.pushDelta(new GridDeltaPayload(
                    payload.getUpdates(), payload.getVolume(), first
            ), grid);
            first = false;

            lastId = rawPage.get(rawPage.size() - 1).getId();

            if (throttleMs > 0) {
                try { Thread.sleep(throttleMs); } catch (InterruptedException ignored) {}
            }
        }

        // —— 冻结色尺（可选）——
        if (!zReservoir.isEmpty()) {
            java.util.Collections.sort(zReservoir);
            int n = zReservoir.size();
            double lo = zReservoir.get((int)Math.floor(n * 0.02));
            double hi = zReservoir.get((int)Math.floor(n * 0.98));
            if (!(hi > lo)) hi = lo + 1.0;
            grid.freezeColorRange(lo, hi);
            log.info("首帧色尺冻结: [{}, {}] via reservoir={}", lo, hi, n);
        }

        log.info("首帧快照完成：epoch={}", epoch);
    }
}
